package org.springframework.boot.autoconfigure.validation;

import org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator;

import javax.validation.*;
import javax.validation.ConstraintViolationException;
import javax.validation.executable.ExecutableValidator;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * 使用hibernate validate进行校验
 */
public class HibernateValidatorUtil {

    private static final ValidatorFactory FACTORY = getValidatorFactory();

    // 空方法，目的是通过调用该方法，可以创建 ValidatorFactory
    public static void init(){

    }
    /**
     * 校验bean的成员变量，如果不符合校验，就抛出异常
     *
     * @param object 被校验的参数
     * @param groups 组
     * @throws javax.validation.ConstraintViolationException 如果校验不成功则抛出异常
     */
    public static <T> void validateBean(T object, Class... groups) {
        //获得验证器
        Validator validator = FACTORY.getValidator();
        //执行验证
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(object, groups);
        //如果有验证信息，则将第一个取出来包装成异常返回
        if(constraintViolations!=null && !constraintViolations.isEmpty()){
            throw new javax.validation.ConstraintViolationException(constraintViolations);
        }
    }
    /**
     * 校验bean的成员变量，如果不符合校验，就抛出异常
     *
     * @param object 校验的对象
     * @param method 校验的方法
     * @param parameters 校验的方法的参数
     * @param groups 组
     * @throws javax.validation.ConstraintViolationException 如果校验不成功则抛出异常
     */
    public static <T> void validateMethodThrow(T object, Method method,Object[] parameters, Class... groups) {
        //获得验证器
        Validator validator = FACTORY.getValidator();
        ExecutableValidator executableValidator = validator.forExecutables();
        //执行验证
        Set<ConstraintViolation<T>> constraintViolations = executableValidator.validateParameters(
                object, method, parameters,groups);
        //如果有验证信息，则将第一个取出来包装成异常返回
        if(constraintViolations!=null && !constraintViolations.isEmpty()){
            throw new ConstraintViolationException(constraintViolations);
        }
    }

    /**
     * 校验方法参数，如果不符合校验规则，就抛出异常
     *
     * @param object 校验的对象
     * @param method 校验的方法
     * @param parameters 校验的方法的参数
     * @param groups 组
     * @throws ConstraintViolationException 如果校验不成功则抛出异常
     */
    public static <T> Set<ConstraintViolation<T>> validateMethodReturn(T object, Method method,Object[] parameters, Class... groups) {
        //获得验证器
        Validator validator = FACTORY.getValidator();
        ExecutableValidator executableValidator = validator.forExecutables();
        //执行验证
        Set<ConstraintViolation<T>> constraintViolations = executableValidator.validateParameters(
                object, method, parameters,groups);

        return constraintViolations;
    }
    /**
     * 获得验证器工厂对象
     * @return
     */
    private static ValidatorFactory getValidatorFactory(){

        //获得验证器
        ValidatorFactory factory = Validation.byDefaultProvider()
                .configure()
                .messageInterpolator(new ParameterMessageInterpolator())
                .buildValidatorFactory();
        return factory;
    }


    /**
     * 从 ConstraintViolation 获取 message提示信息
     * @param set
     * @return
     */
    public static String getMessage(Set<ConstraintViolation<?>> set){
        String res = set
                .stream()
                .map( cv -> {
                        return cv == null ? null : cv.getMessage();
                    })
                .collect(Collectors.joining("; "));

        return res;
    }
}